package whu.cachhe.makeorder.net;

import android.os.AsyncTask;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import whu.cachhe.makeorder.util.BitmapUtil;
import whu.cachhe.makeorder.util.Logger;

/**
 * Created by CocoAdapter on 2018/3/23.
 */

public class HttpRequest {
    /**
     *
     * @param url 相对路径, 会与 #ROOT 进行拼接
     * @param requestBody JSON 请求字符串
     * @param callback 处理网络请求的回调接口
     */

    public static void post(final String url, final String requestBody, final HttpRequestCallback callback){
//        new PostTask(url, requestBody, callback).execute();
    }

    /**
     * 对于 rpc 那种 后台
     * @param url 绝对路径
     * @param fname 函数名
     * @param fparam 参数体
     * @param callback 处理网络请求的回调接口
     */
    public static void post(final String url, final String fname, final Object fparam, final HttpRequestCallback callback){
        new RpcPostTask(url, fname, fparam.toString(), callback).execute();
    }

    public static void post(final String url, final String fname, final Object fparam, File[] files, final HttpRequestCallback callback){
        new RpcFilePostTask(url, fname, fparam.toString(), files, callback).execute();
    }

    /**
     *
     * @param url 相对路径, 会与 #ROOT 进行拼接
     * @param headers headers, 可选
     * @param params form-data 类型的请求参数
     * @param callback 处理网络请求的回调接口
     */
    public static void get(final String url, final Map<String, String> headers,
                           final Map<String, Object> params, final HttpRequestCallback callback) {
//        new GetTask(headers, params, url, callback).execute();
    }

    public interface HttpRequestCallback {
        void onSuccess(JSONObject response);

        void onFailure();
    }

    private static String attachHttpGetParams(String url, Map<String, Object> params){
        if (url == null)
            return null;
        if (params == null || params.isEmpty())
            return url;

        StringBuilder sb = new StringBuilder(url);
        sb.append("?");
        for (Map.Entry<String, Object> entry: params.entrySet()){
            sb.append(entry.getKey());
            sb.append("=");
            sb.append(entry.getValue().toString());
            sb.append("&");
        }
        sb.deleteCharAt(sb.length() - 1);
        return sb.toString();
    }

    private static class RpcFilePostTask extends RpcPostTask {
        private File[] files;

        public RpcFilePostTask(String url, String fname, String fparam, File[] files, HttpRequestCallback callback){
            super(url, fname, fparam, callback);
            this.files = files;
        }

        @Override
        protected String doInBackground(Void... voids) {
            OkHttpClient httpClient = new OkHttpClient.Builder()
                    .addInterceptor(new RetryInterceptor(2))
                    .connectTimeout(5, TimeUnit.SECONDS)
                    .build();

            MultipartBody.Builder builder = new MultipartBody.Builder()
                    .setType(MultipartBody.FORM)
                    .addFormDataPart("fname", fname)
                    .addFormDataPart("fparam", fparam);

            StringBuilder sb = null;
            if (files != null){
                sb = new StringBuilder();
                for (int i = 0; i < files.length; i++){
                    File file = files[i];
                    if (file != null){
                        BitmapUtil.compressFile(file, 1280, 860);
                        RequestBody filePart = RequestBody.create(MediaType.parse("image/*"), file);
                        String fileName = file.getName();
                        builder.addFormDataPart("file[" + i + "]", fileName, filePart);
                        sb.append("file[").append(i).append("] ").append(fileName).append(' ').append((file.length() >> 10)).append("KB").append(' ');
                    }
                }
            }

            Request request = new Request.Builder()
                    .url(url)
                    .post(builder.build())
                    .build();

            try {
                Response response = httpClient.newCall(request).execute();
                Logger.e("HTTP", new Date().toString() + ": " + request.url().toString());
                Logger.e("HTTP", new Date().toString() + ": fname " + fname);
                Logger.e("HTTP", new Date().toString() + ": fparam " + fparam);
                if (sb != null) Logger.e("HTTP", new Date().toString() + ": files" + sb.toString());
                return response.isSuccessful() ? response.body().string() : null;
            } catch (IOException e){
                e.printStackTrace();
            }

            return null;
        }
    }

    private static class RpcPostTask extends AsyncTask<Void, Void, String> {
        protected String url;
        protected String fname;
        protected String fparam;
        protected HttpRequestCallback callback;

        public RpcPostTask(String url, String fname, String fparam, HttpRequestCallback callback) {
            this.url = url;
            this.fname = fname;
            this.fparam = fparam;
            this.callback = callback;
        }

        @Override
        protected void onPostExecute(String resp) {
            Logger.e("HTTP", new Date().toString() + ": response");
            if (resp != null){
                try {
                    Logger.e("HTTP", resp.trim());
                    JSONObject object = new JSONObject(resp);
                    callback.onSuccess(object);
                } catch (JSONException e) {
                    e.printStackTrace();
                    callback.onFailure();
                }
            } else
                callback.onFailure();
        }

        @Override
        protected String doInBackground(Void... voids) {
            OkHttpClient httpClient = new OkHttpClient.Builder()
                    .addInterceptor(new RetryInterceptor(2))
                    .connectTimeout(5, TimeUnit.SECONDS)
                    .build();

            Request request = new Request.Builder()
                    .url(url)
                    .post(RequestBody.create(MediaType.parse("application/x-www-form-urlencoded; charset=utf-8"),
                            "fname=" + fname + "&fparam=" + fparam.toString()))
                    .build();

            try {
                Response response = httpClient.newCall(request).execute();
                Logger.e("HTTP", new Date().toString() + ": " + request.url().toString());
                Logger.e("HTTP", new Date().toString() + ": fname " + fname);
                Logger.e("HTTP", new Date().toString() + ": fparam " + fparam);
                if (response.isSuccessful())
                    return response.body().string();
                else
                    return null;
            } catch (IOException e){
                e.printStackTrace();
            }

            return null;
        }
    }

//    private static class PostTask extends AsyncTask<Void, Void, String> {
//        private String url;
//        private String requestBody;
//        private HttpRequestCallback callback;
//
//        PostTask(String url, String requestBody, HttpRequestCallback callback) {
//            this.url = url;
//            this.requestBody = requestBody;
//            this.callback = callback;
//        }
//
//        @Override
//        protected void onPostExecute(String response) {
//            Logger.e("HTTP", new Date().toString() + ": response");
//            Logger.e("HTTP", response == null ? "null" : response);
//            if (response != null) {
//                try {
//                    JSONObject object = new JSONObject(response);
//                    callback.onSuccess(object);
//                } catch (JSONException e) {
//                    e.printStackTrace();
//                    callback.onFailure();
//                }
//            } else
//                callback.onFailure();
//        }
//
//        @Override
//        protected String doInBackground(Void... params) {
//            OkHttpClient okHttpClient = new OkHttpClient();
//            RequestBody rb = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), requestBody);
//            Request request = new Request.Builder()
//                    .url(URLConstant.ROOT + url)
//                    .post(rb)
//                    .build();
//            try {
//                Response response = okHttpClient.newCall(request).execute();
//                Logger.e("HTTP", new Date().toString() + ": " + request.url().toString());
//                //todo test
//                Logger.e("HTTP", new Date().toString() + ": requestBody");
//                Logger.e("HTTP", requestBody);
//
//                if(response.isSuccessful()){
//                    return response.body().string();
//                } else
//                    return null;
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//            return null;
//        }
//    }
//
//    private static class GetTask extends AsyncTask<Void, Void, String> {
//        private Map<String, String> headers;
//        private Map<String, Object> params;
//        private String url;
//        private HttpRequestCallback callback;
//
//        GetTask(Map<String, String> headers, Map<String, Object> params, String url, HttpRequestCallback callback) {
//            this.headers = headers;
//            this.params = params;
//            this.url = url;
//            this.callback = callback;
//        }
//
//        @Override
//        protected String doInBackground(Void... params) {
//            OkHttpClient httpClient = new OkHttpClient();
//            Request.Builder builder = new Request.Builder();
//            if (headers != null) {
//                for (Map.Entry<String, String> entry : headers.entrySet()) {
//                    builder.addHeader(entry.getKey(), entry.getValue());
//                }
//            }
//
//            if (params != null) {
//                builder.url(attachHttpGetParams(URLConstant.ROOT + url, this.params));
//            } else {
//                builder.url(URLConstant.ROOT + url);
//            }
//
//            Request request = builder.build();
//            Response response;
//            try {
//                response = httpClient.newCall(request).execute();
//                Logger.e("HTTP", new Date().toString() + ": " + request.url().toString());
//                if (!response.isSuccessful()) {
//                    return null;
//                }
//                return response.body().string();
//            } catch (IOException e) {
//                e.printStackTrace();
//                return null;
//            }
//        }
//
//        @Override
//        protected void onPostExecute(String response) {
//            Logger.e("HTTP", new Date().toString() + ": response");
//            Logger.e("HTTP", response == null ? "null" : response);
//            if (response != null) {
//                try {
//                    JSONObject object = new JSONObject(response);
//                    callback.onSuccess(object);
//                } catch (JSONException e) {
//                    e.printStackTrace();
//                    callback.onFailure();
//                }
//            } else
//                callback.onFailure();
//        }
//    }
}
